﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kimd.Common
{
    public class MachineMessageScheduler : SingletonProvider<MachineMessageScheduler>
    {
        private ConcurrentQueue<MachineMessage> _messageQueue;
        private ConcurrentQueue<MachineMessage> _messageQueueLog;
        public int MessageCount 
        {
            get { return _messageQueue.Count; }
        }
        public MachineMessageScheduler()
        {
            this._messageQueue = new ConcurrentQueue<MachineMessage>();
            this._messageQueueLog = new ConcurrentQueue<MachineMessage>();
        }
        public void Add(MachineMessage message)
        {
            
            if (message.MessageType != MessageType.Log&&
                message.MessageType != MessageType.CT &&
                message.MessageType != MessageType.Count &&
                message.MessageType != MessageType.Pie)
            {
                MachineMessage nowMsg = this._messageQueue.FirstOrDefault(msg => msg.Equals(message));
                if (nowMsg == null)
                    this._messageQueue.Enqueue(message);
            }
            else
            {
                MachineMessage nowMsg = this._messageQueueLog.FirstOrDefault(msg => msg.Equals(message));
                if (nowMsg == null)
                    this._messageQueueLog.Enqueue(message);
            }
        }
        public bool GetMessage(out MachineMessage message)
        {
            return _messageQueue.TryDequeue(out message);
        }

        public bool GetMessageLog(out MachineMessage message)
        {
            return _messageQueueLog.TryDequeue(out message);
        }
        public void EmptyMessage()
        {
            while(!_messageQueue.IsEmpty)
            {
                _messageQueue.TryDequeue(out MachineMessage nowMsg);
                System.Threading.Thread.Sleep(10);
            }
            while (!_messageQueueLog.IsEmpty)
            {
                _messageQueueLog.TryDequeue(out MachineMessage nowMsg);
                System.Threading.Thread.Sleep(10);
            }
        }
    }
    public class MachineMessage : ICsv
    {
        public MessageType MessageType { get; set; }
        public string MessageBody { get; set; } = string.Empty;
        public string MessageSource { get; set; } = string.Empty;
        public string Module { get; set; }
        public int ErrorCode { get; set; }
        public MessageOperate MessageOperate { get; set; }
        public DateTime StartTime { get; set; }
        public Exception MessageException { get; set; }
        public SerializableDictionary<string, string> CsvName2Property { get; set; }
        public MachineMessage()
        {

        }
        public MachineMessage(MessageType messageType,
                              string body,
                              string source,
                              int errCode,
                              string module,
                              Exception ex = null)
            : this()
        {
            this.MessageType = messageType;
            this.MessageBody = body;
            this.MessageSource = source;
            this.Module = module;   
            this.ErrorCode = errCode;
            this.StartTime = DateTime.Now;
            this.MessageException = ex;
            this.CsvName2Property = new SerializableDictionary<string, string>();
            this.CsvName2Property.Add("发生时间", nameof(StartTime));
            this.CsvName2Property.Add("报警来源", nameof(MessageSource));
            this.CsvName2Property.Add("报警内容", nameof(MessageBody));
            this.CsvName2Property.Add("所属模组", nameof(Module));
        }
        public override bool Equals(object obj)
        {
            return (obj as MachineMessage).MessageType == this.MessageType &&
                   (obj as MachineMessage).MessageBody == this.MessageBody &&
                   (obj as MachineMessage).MessageSource == this.MessageSource &&
                   (obj as MachineMessage).Module == this.Module &&
                   (obj as MachineMessage).ErrorCode == this.ErrorCode &&
                   (obj as MachineMessage).MessageOperate == this.MessageOperate;
        }
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
    public enum MessageType
    {
        [Description("警报")]
        Warn,
        [Description("错误")]
        Error,
        [Description("提示")]
        Info,
        InfoAndPause,
        Log,
        CT,
        Count,
        Pie
    }
    public enum MessageOperate
    {
        Auto,
        Manual,
    }
}
